package com.jacen.aws.service;

import com.alibaba.fastjson.JSON;
import com.jacen.aws.client.Ec2Client;
import com.jacen.aws.entity.KeyEntity;
import com.jacen.aws.entity.vo.AddressVo;
import com.jacen.aws.entity.vo.InstanceVo;
import com.jacen.aws.entity.vo.ViewVo;
import com.jacen.aws.exception.ClientException;
import com.jacen.aws.setting.Setting;
import com.jacen.aws.util.FileUtil;
import com.jacen.aws.util.LogUtil;
import com.jacen.aws.util.StringUtil;

import javax.swing.*;
import java.io.File;
import java.util.List;
import java.util.Vector;

/**
 * 版权声明：Copyright(c) 2018 All Rights Reserved.
 *
 * @Author Jacen (295117485@qq.com)
 * @Date 2018/10/13 8:36
 * @Version 1.0
 * @Description ip服务类
 */
public class IpService {

    /**
     * 重试次数
     */
    public static final int RETRY_TIMES = 3;

    /**
     * 读取
     *
     * @param view
     */
    public static void read(ViewVo view) throws ClientException {
        KeyEntity keyEntity = view.getKeyEntity();
        String instanceId = keyEntity.getInstanceId();
        JTextArea logText = view.getTextArea();
        JTextField txtPublicIp = view.getTxtPublicIp();
        Vector<String> ips = view.getIpWhiteList();
        InstanceVo instanceVo = Ec2Client.describeInstances(keyEntity);
        LogUtil.printMessage(logText, "读取实例信息：", JSON.toJSONString(instanceVo));
        //获取弹性ip列表
        List<AddressVo> addressList = Ec2Client.describeAddressList(keyEntity);
        if (Setting.ELASTIC_YES == instanceVo.getElastic()) {
            txtPublicIp.setText(instanceVo.getPublicIp());
            //有弹性ip
            for (AddressVo address : addressList) {
                if (Setting.USE_YES == address.getUse()) {
                    continue;
                }
                //白名单判断
                if (ips != null) {
                    if (ips.contains(address.getPublicIp())) {
                        continue;
                    }
                }
                //释放空闲的ip
                Ec2Client.releaseAddressRequestWithLocationId(keyEntity, address.getAllocationId());
                LogUtil.printMessage(logText, "释放空闲ip：" + address.getPublicIp());
            }
        } else {
            if (addressList.size() == 0) {
                allocateAndAssociateAddress(view, RETRY_TIMES);
            } else {
                boolean flag = false;
                for (AddressVo addressVo : addressList) {
                    if (Setting.USE_NO == addressVo.getUse()) {
                        if (ips != null) {
                            if (ips.contains(addressVo.getPublicIp())) {
                                continue;
                            }
                        }
                        //ec2关联ip
                        Ec2Client.associateAddressRequest(keyEntity, addressVo.getPublicIp());
                        LogUtil.printMessage(logText, "实例关联ip成功：" + instanceId + ":" + addressVo.getPublicIp());
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    allocateAndAssociateAddress(view, RETRY_TIMES);
                }
            }
        }
    }

    /**
     * 切换
     *
     * @param view
     */
    public static void change(ViewVo view) throws ClientException {
        KeyEntity keyEntity = view.getKeyEntity();
        String instanceId = keyEntity.getInstanceId();
        JTextArea logText = view.getTextArea();
        Vector<String> ips = view.getIpWhiteList();
        //获取弹性ip列表
        List<AddressVo> addressList = Ec2Client.describeAddressList(keyEntity);
        AddressVo address = null;
        for (AddressVo addressVo : addressList) {
            if (Setting.USE_NO == addressVo.getUse()) {

                if (ips != null) {
                    if (ips.contains(addressVo.getPublicIp())) {
                        continue;
                    }
                }

                address = addressVo;
                break;
            }
        }

        if (address != null) {
            Ec2Client.associateAddressRequest(keyEntity, address.getPublicIp());
            view.getTxtPublicIp().setText(address.getPublicIp());
            LogUtil.printMessage(logText, "实例切换ip成功：" + instanceId + ":" + address.getPublicIp());
        } else {
            allocateAndAssociateAddress(view, RETRY_TIMES);
        }

        //获取弹性ip列表
        addressList = Ec2Client.describeAddressList(keyEntity);
        for (AddressVo addressVo : addressList) {
            if (Setting.USE_NO == addressVo.getUse()) {

                if (ips != null) {
                    if (ips.contains(addressVo.getPublicIp())) {
                        continue;
                    }
                }
                Ec2Client.releaseAddressRequestWithLocationId(keyEntity, addressVo.getAllocationId());
                LogUtil.printMessage(logText, "释放空闲ip成功：" + addressVo.getPublicIp());
            }
        }
    }

    /**
     * 分配并关联
     *
     * @param view
     * @throws ClientException
     */
    public static void allocateAndAssociateAddress(ViewVo view, int num) throws ClientException {
        if (num == 0) {
            LogUtil.printMessage(view.getTextArea(), "分配弹性ip超过限制，请重试!!!");
            return;
        }
        KeyEntity keyEntity = view.getKeyEntity();
        String instanceId = keyEntity.getInstanceId();
        //分配ip
        AddressVo addressVo = Ec2Client.allocateAddress(keyEntity);
        if (isBlackIp(view.getIpBlackList(), addressVo.getPublicIp())) {
            //递归调用
            LogUtil.printMessage(view.getTextArea(), "分配弹性ip在黑名单中：" + addressVo.getPublicIp(), "重新分配中" + instanceId);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            num--;
            allocateAndAssociateAddress(view, num);
        }
        //ec2关联新ip
        Ec2Client.associateAddressRequest(keyEntity, addressVo.getPublicIp());
        view.getTxtPublicIp().setText(addressVo.getPublicIp());
        LogUtil.printMessage(view.getTextArea(), "分配弹性ip成功：" + addressVo.getPublicIp(), "关联实例成功：" + instanceId);
    }


    /**
     * 关联
     *
     * @param view
     * @throws ClientException
     */
    public static void associateAddress(ViewVo view, String publicIp) throws ClientException {
        KeyEntity keyEntity = view.getKeyEntity();
        String instanceId = keyEntity.getInstanceId();

        //ec2关联新ip
        Ec2Client.associateAddressRequest(keyEntity, publicIp);
        view.getTxtPublicIp().setText(publicIp);
        LogUtil.printMessage(view.getTextArea(), "弹性ip：" + publicIp, "关联实例成功：" + instanceId);
    }

    /**
     * @param ip
     * @throws Exception
     */
    public static void saveToIpList(String fileName, String ip) throws Exception {
        File file = new File(fileName);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileUtil.append(fileName, ip + "\r\n");
    }

    /**
     * 读取ip列表
     *
     * @return
     * @throws Exception
     */
    public static Vector<String> readIpList(String fileName) throws Exception {
        File file = new File(fileName);
        if (!file.exists()) {
            file.createNewFile();
            return null;
        }
        String txt = FileUtil.readTxtFile(fileName);
        if (StringUtil.isEmpty(txt)) {
            return null;
        }
        String[] ips = txt.split("\r\n");
        Vector<String> vector = new Vector<>();
        for (String ip : ips) {
            vector.add(ip);
        }
        return vector;
    }

    private static boolean isBlackIp(Vector<String> blackIpList, String publicIp) {
        if (blackIpList == null) {
            return false;
        }
        boolean isBlack = false;
        for (String ip : blackIpList) {
            if (publicIp.startsWith(ip)) {
                isBlack = true;
                break;
            }
        }
        return isBlack;
    }

}
